---
title: 关于 OpenDigger 标签工作的思考与规划
authors: [zsy]
slug: 2024-12-09-thoughts-on-label-work
---

> 这段时间，对 OpenDigger 的标签做了一次较大的更新，主要是新增了一批项目和企业的标签，以及对国家和地区的开发者占比做了统计，主要用于 BenchCouncil 中的榜单发布（[全球行政区划开发者 OpenRank 排行榜](https://open-digger.cn/leaderboards?type=divisions), [全球企业 OpenRank 排行榜](https://open-digger.cn/leaderboards?type=companies), [全球项目 OpenRank 排行榜](https://open-digger.cn/leaderboards?type=projects)）。因此也有了一些新的思考，这里分享一下，也希望可以抛砖引玉，看接下来如何进一步规划和优化 OpenDigger 的标签体系。

总体而言，OpenDigger 的标签工作分为两部分，标签体系建设和标签工具建设。标签体系的重点在于如何构建以一套有效且易维护的标签结构，而标签工具则是使用怎样的技术方案来实现和维护上述的标签体系。

## 标签体系建设

OpenDigger 的标签体系早期是源于 OpenDigger 本身的数据需求而逐渐建立起来的。主要是各类数据报告中需要有不同的指标聚合方式，尤其是如企业、国家维度的聚合，所以最初的设计中最主要标注的也就是企业、国家的数据，后续又陆续增加了基金会、技术领域和项目群的相关标签。然而随着标签数据越来越多，维护的难度也开始逐渐上升，缺乏顶层设计的缺陷也逐渐凸显。截止到 2024 年 12 月，已经有上千个标签，涵盖 200 多家企业、数十个基金会和 500 多个项目，这也需要 OpenDigger 建立一套标准化的标签体系，方便后续的持续维护和进一步拓展。

总体而言，早期标签的加入是需求驱动的，并没有进行顶层的统一设计，因此结构上也是趋向于扁平化的，即每类标签单独在一个文件夹下，通过标签之间的 ID 进行交叉引用。但在过去一段时间丰富标签的过程中，发现目前主要的标签需求之间其实存在某种关联性，这种关联性也进而导致了后续的一些设计上的变化，例如：

- 项目一般都是由某个实体发起，后续可能捐献给基金会的，因此项目可以不单独使用某个目录，而是在其对应的发起实体的目录下维护。
- 项目发起的实体可以是个人、企业、高校、政府机构（如美国退伍军人事务部、英国司法部）、研究机构（如欧洲核子研究中心）等。这些实体的类型不一而足，但大多与各国当地的机构结构有关，因此总体上虽然结构相似，但在不同国家也会有细微的差异。
- 对于上述的各类实体，需要一套标准化可行的分类方式，这种分类方式不仅体现在维护性上，而且也是后续各种聚合查询的基础，因为构建在这套标签体系之上的指标查询工具将使用这套标签体系来进行查询。

基于上述的一些反思，因此对于指标体系的建设可以从几个方面来说：

### 指标结构

从指标结构上来说，之前是扁平化展开的，国家、企业、基金会、高校、机构、项目都是放在同级目录下的，然后会进行交叉引用，例如国家会以高校、企业、基金会等为子标签。然而上述的标签其实都是从项目发起方的角度来看的，因此应该可以构建在同一个目录下，形成“行政区划”-“发起机构”-“开源项目”的三层结构。

- 行政区划一级主要是指地区信息，如国家，当然也可以更进一步细化到省市一级。
- 发起机构则是指在法律上实体注册在这些行政区划内的机构，这些机构本身可以进一步进行分类，关于这个分类方法后续再进一步讨论。
- 项目就是 GitHub、Gitee 上的组织或仓库群构成的开源项目，同一个开源项目可以包含多个组织或仓库，也可以托管在多个平台上。

上述的发起方角度应该是整个标签体系构建的基础，在此基础之上，可以进一步增加其他的并行标签内容，如项目类型、技术领域等，这些标签均以项目标签为基础构建，即它们仅可引用项目级标签为自己的子标签，而不能单独使用平台上的仓库或组织为自己的标签数据内容。即当某个领域出现一个新的项目要标注时，需要先鉴别其对应的发起方及其所在的行政区划，并设置好这些数据后引用该项目标签，而不要直接使用仓库或组织数据。

### 行政区划

行政区划是发起方所属国家或地区的信息，这部分事实上已经有一些标准可以直接采用。例如 OpenDigger 目前使用 [ISO 3166](https://en.wikipedia.org/wiki/ISO_3166) 标准进行国家标注，国家和地区编码部分使用的是 [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) 标准，该标准下所有国家和地区使用一个 2 位的英文字母进行标识，同时也包含该国家对应的全称，而恰好 GitHub 发布的[全球开发者区划分布](https://innovationgraph.github.com/global-metrics/developers)也是按照该标准发布（区别在于该数据将欧盟作为一个一级区划），因此较容易进行关联性建立。而对应的 [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) 标准则进一步对国家和地区内部的一级行政区划进行了定义，因此国家和国家内部的一级行政区划可以完全使用 ISO 3166 系列标准进行定义。

### 发起主体

> 这部分需要比较专业的知识，可能本人的理解也有出入，欢迎指出。

如上所述，发起主体与各国中对于法律实体的定义有关，因此情况也最为复杂。相对而言，高校、政府机构、研究机构是相对明确简单的，而企业和基金会是最为复杂的。

以中美的差异为例，对于大部分企业而言其结构是相似的，尤其是私营企业主要以独资企业、合伙企业、有限责任公司、股份有限公司等形式为主，在 OpenDigger 的标签体系中可以不做额外的区分，就是公司/企业标签即可。主要难点在于基金会的分类：

在中国的实体分类中，一般性企业属于工商部管理范畴，而社会团体、民办非企业单位和基金会则属于民政部管理范畴，这也是为什么国内部分唯二的开源基金会（开放原子开源基金会、重庆开工开物开源基金会）都注册在民政部，其对应的统一社会信用代码以 53 开头，即民政部下属基金会属性单位。可见基金会在中国是一个独立的法人实体类型。且在中国，法律认可的非营利性组织也只有社会团体、民办非企业单位和基金会三类。

<img src="/img/blogs/label_data/foundations_cn.png" style={{height:"200px",display:"block",margin:"auto"}}/>

但在美国的法律体系中，并不包含一种名为基金会的法人实体，所有的非营利组织在美国都属于企业性质，只是分类会略有不同，主要都在 [501(c)](https://en.wikipedia.org/wiki/501(c)_organization) 分类下。常见的非营利组织类型包括慈善组织 501(c)(3)，如 Apache 基金会就是这类组织；还有商业联盟性质的 501(c)(6)，如 Linux 基金会就属于这类组织。它们在财务规定和监管层面有一定的差异，这也是为什么近年来 Linux 基金会可以通过企业捐赠快速扩张发展，而 Apache 基金会则更加佛系的根本原因之一。

也正是由于上述区别，基金会这个名称在中美有了很大的差异，在中国是一类非常明确的法人实体类型，而在美国基金会是非营利组织可选的一种注册名称而已。如美国的[连接标准联盟](https://en.wikipedia.org/wiki/Connectivity_Standards_Alliance)与 Linux 基金会相同也是一个 501(c)(6) 组织，但其名称确为"联盟"。而正是由于这种命名的随意性，使得追踪海外基金会变得非常困难，例如一些自称为基金会的组织，我们甚至在网上无法查证其组织类型以及是否真的是非营利性的组织。

另外一个有趣的差别是，在美国，在一般性企业和非营利性组织之间，还存在一种叫做 PBC（Public Benefit Corporation） 的企业类型，即公益法团。如最近大火的社交平台 [Bluesky](https://en.wikipedia.org/wiki/Bluesky) 背后的公司即属于这类。该类型是一种具有公益性质的营利性组织。对应中文语境中的“社会企业”，但在中国，目前“社会企业”还并非一种具有法律认可的实体类型，主要是由中国慈展会定期进行公开评定，可给各类企业或非营利性组织进行非正式的社会企业认证。当然，在 OpenDigger 的标签体系中，这类还是统一被归为企业类型。

综上所述，在发起主体层面，除明确的高校（University）、政府机构（Agency）、研究机构（Institution）外，其他则分为公司（Company）和非营利组织（NPO）。则在各国法律体系下，基金会均属于非营利组织范畴，而基金会排名对比时则也是与其他非营利组织统一排名，如行业联盟等。

### 社区项目

虽然上面提到在新的设计中，我们希望为所有项目均找到对应的法人实体发起方。但在现实中，依然会存在没有明确发起人的项目，或发起人希望该项目是完全社区驱动的，又或者发起人为个人的项目，这类项目难以对应到具体的法人实体，因此需要一个社区项目类型来涵盖这部分项目。

需要注意的是这里的社区也只是一种无明确发起方的分类方式，而社区（Community）本身并不是 OpenDigger 标签体系中的一部分。这是由于我发现社区本身的定义非常宽泛和模糊，一个企业项目也可以称自己为社区，一个兴趣团体也可以称自己为社区，因此这会导致该标签可能被滥用，而其对应的排行也就没有太多意义了。不过可能确实存在某些群体需要一个独立身份的情况，后续可能根据需求的变化会进一步细化这部分设计。

### 总结

因此最新的设计下，总体的标签结构示例应该为：

```shell
label_data
├── division # 行政区划
│   ├── cn # 中国
│   │   ├── gd # 广东
│   │   │   └── huawei # 华为
│   │   │       └── openharmony
│   │   └── zj # 浙江
│   │       └── alipay # 蚂蚁集团
│   │           └── tugraph
│   └── us # 美国
│       ├── ca # 加利福尼亚州
│       │   └── linux_foundation # Linux 基金会
│       │       └── valkey
│       └── md # 马里兰州
│           └── apache_software_foundation # Apache 软件基金会
└── technology # 技术领域
    ├── cloud_native # 云原生
    │   ├── platform # 平台
    │   └── runtime # 运行时
    └── database # 数据库
        ├── graph # 图数据库 -> 引用 :division/cn/zj/alipay/tugraph
        └── kv # 键值数据库 -> 引用 :division/us/ca/linux_foundation/valkey
```

## 标签工具建设

标签工具建设是更加偏向技术的一部分，是上述标签体系的具体实现。该实现不仅需要考虑到上述标签体系的所有能力和业务需求，同时也需要向下适配与数据库交互的结构以及标签数据的常见运算，如集合的交并差等。

目前的标签工具是使用 TypeScript 编写的，直接在运行时基于标签数据文件在内存中构建整套标签数据，可实现基础的运算和标签关系查询能力。但长远而言，从可扩展性以及查询效率上，还是希望标签数据可以直接落库，则最终的指标查询只需要做一个联表查询即可。

但由于存在多层标签的父子标签溯源问题（如某个项目是哪个国家发起的），这种溯源在数据库中需要[递归 CTEs](https://en.wikipedia.org/wiki/Hierarchical_and_recursive_queries_in_SQL) 特性的支持，而 OpenDigger 目前底层的 ClickHouse 版本尚不支持该特性，因此需要等待 ClickHouse 升级后再进行改造。
